/*              Copyright(c) 2008 Dave Sexton              *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace DaveSexton.Sandcastle
{
	internal sealed partial class DatabaseUrlMappingProviderEditor : UserControl
	{
		#region Public Properties
		public string Configuration
		{
			get
			{
				return CreateConfiguration();
			}
			set
			{
				Initialize(value);
			}
		}
		#endregion

		#region Private / Protected
		private readonly DataTable parametersTable = CreateParametersDataTable();
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="DatabaseUrlMappingProviderEditor" /> class.
		/// </summary>
		public DatabaseUrlMappingProviderEditor()
		{
			InitializeComponent();

			parametersBindingSource.DataSource = parametersTable;

			providerComboBox.DataSource = System.Data.Common.DbProviderFactories.GetFactoryClasses();
			providerComboBox.DisplayMember = "Name";
			providerComboBox.ValueMember = "InvariantName";

			foreach (string name in Enum.GetNames(typeof(DatabaseParameterSourceType)))
				sourceColumn.Items.Add(name);
		}
		#endregion

		#region Methods
		private static DataTable CreateParametersDataTable()
		{
			DataTable table = new DataTable();
			table.Locale = System.Globalization.CultureInfo.CurrentCulture;

			DataColumn name = table.Columns.Add("name", typeof(string));
			table.PrimaryKey = new DataColumn[] { name };

			DataColumn value = table.Columns.Add("value", typeof(string));
			value.AllowDBNull = false;
			value.DefaultValue = string.Empty;

			DataColumn source = table.Columns.Add("source", typeof(string));
			source.AllowDBNull = false;
			source.DefaultValue = DatabaseParameterSourceType.Value.ToString();

			return table;
		}

		private string CreateConfiguration()
		{
			parametersDataGridView.EndEdit();

			StringBuilder output = new StringBuilder(1024);

			System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings();
			settings.Indent = true;
			settings.ConformanceLevel = System.Xml.ConformanceLevel.Fragment;

			using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(output, settings))
			{
				WriteConnection(writer);
				WriteQuery(writer);
				WriteParameters(writer);
			}

			return output.ToString();
		}

		private void WriteConnection(System.Xml.XmlWriter writer)
		{
			writer.WriteStartElement("connection");

			if (providerComboBox.SelectedIndex > -1)
				writer.WriteAttributeString("provider", (string) providerComboBox.SelectedValue);
			else if (!string.IsNullOrEmpty(providerComboBox.Text))
				writer.WriteAttributeString("provider", providerComboBox.Text);

			writer.WriteString(Environment.NewLine + connectionStringTextBox.Text + Environment.NewLine);
			writer.WriteEndElement();
		}

		private void WriteQuery(System.Xml.XmlWriter writer)
		{
			writer.WriteStartElement("query");

			if (storedProcedureCheckBox.Checked)
				writer.WriteAttributeString("storedProcedure", "True");

			if (idColumnTextBox.TextLength > 0)
			{
				string id = idColumnTextBox.Text;

				if ((id = id.Trim()).Length > 0 && !string.Equals(id, DatabaseUrlMappingProviderSettings.DefaultIdColumnName, StringComparison.OrdinalIgnoreCase))
					writer.WriteAttributeString("idColumn", id);
			}

			if (hrefColumnTextBox.TextLength > 0)
			{
				string href = hrefColumnTextBox.Text;

				if ((href = href.Trim()).Length > 0 && !string.Equals(href, DatabaseUrlMappingProviderSettings.DefaultHrefColumnName, StringComparison.OrdinalIgnoreCase))
					writer.WriteAttributeString("hrefColumn", href);
			}

			if (timeoutCheckBox.Checked)
				writer.WriteAttributeString("timeout", timeoutNumericUpDown.Value.ToString(System.Globalization.CultureInfo.CurrentCulture));

			writer.WriteString(Environment.NewLine + queryTextBox.Text + Environment.NewLine);
			writer.WriteEndElement();
		}

		private void WriteParameters(System.Xml.XmlWriter writer)
		{
			if (parametersTable.Rows.Count > 0)
			{
				writer.WriteStartElement("parameters");

				foreach (DataRow row in parametersTable.Rows)
				{
					writer.WriteStartElement("parameter");
					writer.WriteAttributeString("name", (string) row["name"]);

					string source = (string) row["source"];

					if (string.Equals(source, DatabaseParameterSourceType.Value.ToString(), StringComparison.Ordinal))
						writer.WriteAttributeString("value", (row.IsNull("value")) ? "" : (string) row["value"]);
					else
						writer.WriteAttributeString("source", source);

					writer.WriteEndElement();
				}

				writer.WriteEndElement();
			}
		}

		private void Initialize(string configuration)
		{
			parametersBindingSource.SuspendBinding();

			try
			{
				connectionStringTextBox.Text = null;
				providerComboBox.SelectedValue = "System.Data.OleDb";
				queryTextBox.Text = null;
				timeoutCheckBox.Checked = false;
				timeoutNumericUpDown.Value = 0;
				storedProcedureCheckBox.Checked = false;
				idColumnTextBox.Text = DatabaseUrlMappingProviderSettings.DefaultIdColumnName;
				hrefColumnTextBox.Text = DatabaseUrlMappingProviderSettings.DefaultHrefColumnName;
				parametersTable.Clear();

				if (!string.IsNullOrEmpty(configuration))
				{
					System.Xml.XmlReaderSettings settings = new System.Xml.XmlReaderSettings();
					settings.IgnoreWhitespace = true;
					settings.IgnoreComments = true;
					settings.IgnoreProcessingInstructions = true;
					settings.ConformanceLevel = System.Xml.ConformanceLevel.Fragment;

					using (System.IO.StringReader input = new System.IO.StringReader(configuration))
					{
						using (System.Xml.XmlReader reader = System.Xml.XmlReader.Create(input, settings))
						{
							Initialize(reader);
						}
					}
				}

				parametersTable.AcceptChanges();
			}
			finally
			{
				parametersBindingSource.ResumeBinding();
			}
		}

		private void Initialize(System.Xml.XmlReader reader)
		{
			DatabaseUrlMappingProviderSettings settings = DatabaseUrlMappingProvider.ReadConfiguration(reader, 0);

			if (!string.IsNullOrEmpty(settings.Provider))
			{
				providerComboBox.SelectedValue = settings.Provider;

				if (providerComboBox.SelectedIndex == -1)
					providerComboBox.Text = settings.Provider;
			}

			connectionStringTextBox.Text = settings.Connection;
			storedProcedureCheckBox.Checked = settings.StoredProcedure;
			timeoutNumericUpDown.Value = (settings.CommandTimeout == null) ? 0 : settings.CommandTimeout.Value;
			idColumnTextBox.Text = settings.IdColumn;
			hrefColumnTextBox.Text = settings.HrefColumn;
			queryTextBox.Text = settings.Query;

			if (settings.Parameters != null)
				InitializeParameters(settings.Parameters);
		}

		private void InitializeParameters(IEnumerable<QueryParameter> parameters)
		{
			foreach (QueryParameter parameter in parameters)
			{
				DataRow row = parametersTable.NewRow();
				row["name"] = parameter.ParameterName;
				row["source"] = parameter.Source.ToString();

				if (parameter.ParameterValue != null)
					row["value"] = parameter.ParameterValue;

				parametersTable.Rows.Add(row);
			}
		}
		#endregion

		#region Event Handlers
		private void timeoutCheckBox_CheckedChanged(object sender, EventArgs e)
		{
			timeoutNumericUpDown.Enabled = timeoutCheckBox.Checked;
		}
		#endregion
	}
}
